package com.laopan.wxpay.utils;


import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.Base64Utils;

import java.nio.charset.StandardCharsets;
import java.security.*;
import java.security.cert.X509Certificate;

/**
 * 签名的工具类。 微信支付v3会用这个类，对请求的内容进行签名。
 *
 * @author 微信SDK 自带
 * @className SHA256SignUtils
 * @date 2021/2/22 13:46
 */
public class SignUtils {
    private final static Logger LOGGER = LoggerFactory.getLogger(SignUtils.class);

    /**
     * 使用给定的密钥，对指定的buffer进行签名
     *
     * @param privateKey 给定的密钥。
     * @param message    需要签名的消息
     * @return 返回签名后的buffer
     */
    public static byte[] sign(PrivateKey privateKey, byte[] message)
            throws NoSuchAlgorithmException, InvalidKeyException, SignatureException {
        Signature sign = Signature.getInstance("SHA256withRSA");
        sign.initSign(privateKey);
        sign.update(message);
        return sign.sign();
    }

    /**
     * 将一个String字符串进行签名。
     *
     * @param privateKey
     * @param message
     * @return
     * @throws NoSuchAlgorithmException
     * @throws InvalidKeyException
     * @throws SignatureException
     */
    public static String signString(PrivateKey privateKey, String message)
            throws NoSuchAlgorithmException, InvalidKeyException, SignatureException {
        return new String(sign(privateKey, message.getBytes()), StandardCharsets.UTF_8);
    }

    /**
     * 对给定的字符串进行签名，并将签名后的内容转换成base64编码。
     *
     * @param privateKey
     * @param message
     * @return
     */
    public static String signAndEncodeWithBase64(PrivateKey privateKey, String message)
            throws NoSuchAlgorithmException, InvalidKeyException, SignatureException {
        return Base64Utils.encodeToString(sign(privateKey, message.getBytes()));
    }

    /**
     * 验证回调的信息签名是不是正确
     *
     * @param certificate
     * @param signStr
     * @param wechatSign
     * @return
     */
    public static boolean verify(X509Certificate certificate, String signStr, String wechatSign) {
        try {
            Signature sign = Signature.getInstance("SHA256withRSA");
            sign.initVerify(certificate);
            sign.update(signStr.getBytes());
            return sign.verify(Base64Utils.decode(wechatSign.getBytes()));
        } catch (Exception e) {
            LOGGER.error("验证签名异常", e);
        }
        return false;
    }

}
